#include "ErrMsgRecord.h"

/*============================================================================
 钩子函数，存储设备读，需用户根据实际硬件填充
 addr：存储设备地址
 pDes：目标地址
 len：长度
 retval：成功/失败
 ============================================================================*/
static E_EMR_STATE hook_flash_read(uint32_t addr,uint8_t *pDes,uint16_t len)
{
    E_EMR_STATE res = E_EMR_OK;

    return res;
} 
/*============================================================================
 钩子函数，存储设备写，需用户根据实际硬件填充
  addr：存储设备地址
 pSrc：源地址
 len：长度
 retval：成功/失败
 ============================================================================*/
static E_EMR_STATE hook_flash_write(uint32_t addr,uint8_t *pSrc,uint16_t len)
{
    E_EMR_STATE res = E_EMR_OK;

    return res;
}

/*============================================================================
 EMR初始化
 retval：成功/失败
 ============================================================================*/
E_EMR_STATE api_EMR_Reset(void)
{
    E_EMR_STATE res = E_EMR_OK;

    uint16_t arr[2] = {0,0};
    res = hook_flash_write(EMR_START_ADDR,(uint8_t *)arr,sizeof(arr));

    return res;
}

/*============================================================================
 EMR写一条异常记录
 pSrc：错误记录指针
 retval：成功/失败
 ============================================================================*/
E_EMR_STATE api_EMR_WriteOne(T_ErrMsgInfo *pSrc)
{
    E_EMR_STATE res = E_EMR_OK;
    uint32_t addr;
    uint16_t point,cycle,arr[2];
    //读索引
    res = hook_flash_read(EMR_START_ADDR,(uint8_t *)&arr,sizeof(arr));
    if(res != E_EMR_OK)
    {
        goto exit;
    }

    point = arr[0];
    cycle = arr[1];
    //索引有效性判断
    if(point >= EMR_ERR_MSG_NBR)
    {
        res = E_EMR_ERR;
        goto exit;
    }

    //写数据
    addr = EMR_START_ADDR + 2 * sizeof(uint16_t) + point * sizeof(T_ErrMsgInfo);
    res = hook_flash_write(addr,(uint8_t *)pSrc,sizeof(T_ErrMsgInfo));
    if(res != E_EMR_OK)
    {
        goto exit;
    }

    //更新索引
    point++;
    if(point >= EMR_ERR_MSG_NBR)
    {
        point = 0;
        cycle++;
    }

    arr[0] = point;
    arr[1] = cycle;

    res = hook_flash_write(EMR_START_ADDR,(uint8_t *)arr,sizeof(arr));
    if(res != E_EMR_OK)
    {
        goto exit;
    }

exit:
    return res;
}

/*============================================================================
 EMR读最近N条异常记录
 pDes：目的地址
 N：欲读取的记录条数
 desArrSize：目的数组长度 安全防护 防溢出用
 retval：读到的记录条数 -1为失败
 ============================================================================*/
int16_t api_EMR_ReadN(T_ErrMsgInfo *pDes,uint16_t N,uint16_t desArrSize)
{
    int16_t res = 0;
    E_EMR_STATE read_res = E_EMR_OK;
    uint32_t addr;
    uint16_t point,cycle,arr[2],i;

    //读索引
    read_res = hook_flash_read(EMR_START_ADDR,(uint8_t *)&arr,sizeof(arr));
    if(read_res != E_EMR_OK)
    {
        res = -1;
        goto exit;
    }

    point = arr[0];
    cycle = arr[1];

    //有效性介入 确定最终有效的N
    if(N > EMR_ERR_MSG_NBR)
    {
        N = EMR_ERR_MSG_NBR;
    }

    if(N > point)
    {
        if(cycle == 0)
        {
            N = point;
        }
    }
    
    //防溢出介入 确定最终有效且不会溢出的N
    if(desArrSize < N * sizeof(T_ErrMsgInfo))
    {
        N = desArrSize / sizeof(T_ErrMsgInfo);
    }

    //读取
    for(i = 0 ; i < N; i++)
    {
        if(point == 0)
        {
            point = EMR_ERR_MSG_NBR - 1;
        }
        else
        {
            point--;
        }
        
        addr = EMR_START_ADDR + 2 * sizeof(uint16_t) + point * sizeof(T_ErrMsgInfo);
        read_res = hook_flash_read(addr,(uint8_t *)(pDes + i),sizeof(T_ErrMsgInfo));
        if(read_res != E_EMR_OK)
        {
            goto exit;
        }
        else
        {
            res++;
        }
        
    }

exit:
    return res;
}